/*
 * gx_array.c
 *
 *  Created on: Apr 10, 2012
 *      Author: zhanggx
 */

#include "gx_array.h"
#include "gx_os_utils.h"

#define MAGIC_INIT_NUMBER 0xfe34ab02
int
gx_array_is_init(gx_array_t* array){
	return array->is_init == MAGIC_INIT_NUMBER;
}
int
gx_array_init(gx_array_t* array, gx_int32_t capacity, gx_int32_t elt_size) {
	assert(array!=NULL);
	assert(elt_size > 0);
	assert(capacity > 0);

	array->head = gx_malloc(capacity * elt_size);
	if(!array->head)
		return -1;
	array->capacity = capacity;
	array->elt_size	= elt_size;

	array->nelts = 0;
	array->is_init = MAGIC_INIT_NUMBER;
	return 0;
}

#define GX_ARRAY_EXPAND_PARAM 1.5

void* gx_array_push(gx_array_t* array) {
	assert(array!=NULL);
	array->nelts++;
	if (array->nelts == array->capacity) {
		//reallocate and copy
		void* new_head = gx_malloc(array->capacity * GX_ARRAY_EXPAND_PARAM * array->elt_size);
		memcpy(new_head, array->head, array->capacity * array->elt_size);
		gx_free(array->head);
		array->capacity = array->capacity * GX_ARRAY_EXPAND_PARAM;
		array->head 	= new_head;
	}

	return (gx_uint8_t*)(array->head) + ((array->nelts - 1) * array->elt_size);
}

void*
gx_array_get(gx_array_t* array, int index){
	assert(array != NULL);
	assert(index >= 0);
	assert(index < array->nelts);

	return (gx_uint8_t*)(array->head) + (index * array->elt_size);
}

void gx_array_destroy(gx_array_t* array){
	assert(array != NULL);

	array->nelts = 0;
	gx_free(array->head);
}
